package chatsystem;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import protocol.Signal;

/**
 *
 * @author ernestoexposito
 */
public class TCPNI implements Runnable {

    private Socket socket;
    private ServerSocket server;
    private Thread thread;
    private boolean active = true;
    private ChatSystemControler controller;
    private int port;
    private java.io.BufferedWriter out;
    private java.io.BufferedReader in;

    public TCPNI(int port, ChatSystemControler controller) {
        this.controller = controller;
        this.port = port;
        thread = new Thread(this);
        thread.start();
    }

    public TCPNI(int port, InetAddress destination, ChatSystemControler controller) throws IOException {
        this.controller = controller;
        this.port = port;
        socket = new Socket(destination, port);
        thread = new Thread(this);
        thread.start();

    }

    public void sendFile(Signal s, User dest) {
        try {            
            int length = 4096;
            byte[] buf = new byte[length];
            
            buf = s.serializer();
            
            System.out.println("sending via TCP");
            sendBytes(buf);

        } catch (IOException ex) {
            System.out.println("Error sending data via TCP");
        }
    }

    public void sendBytes(byte[] myByteArray) throws IOException {
        sendBytes(myByteArray, 0, myByteArray.length);
    }

    public void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
        if (len < 0)
            throw new IllegalArgumentException("Negative length not allowed");
        if (start < 0 || start >= myByteArray.length)
            throw new IndexOutOfBoundsException("Out of bounds: " + start);
        // Other checks if needed.

        // May be better to save the streams in the support class;
        // just like the socket variable.
        OutputStream outs = socket.getOutputStream(); 
        DataOutputStream dos = new DataOutputStream(outs);

        dos.writeInt(len);
        if (len > 0) {
            dos.write(myByteArray, start, len);
        }
    }
    
    public byte[] readBytes() throws IOException {
        // Again, probably better to store these objects references in the support class
        InputStream ins = socket.getInputStream();
        DataInputStream dis = new DataInputStream(ins);

        int len = dis.readInt();
        byte[] data = new byte[len];
        if (len > 0) {
            dis.readFully(data);
        }
        return data;
    }
    
    public void run() {
        if (socket == null) {
            try {

                server = new ServerSocket(port);
                socket = server.accept();
                //server.close();
            } catch (IOException ex) {
                System.out.println("Error with the TCP server, " + ex.getMessage());
            }
        }
        try {
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (IOException ex) {
            Logger.getLogger(TCPNI.class.getName()).log(Level.SEVERE, null, ex);
        }
        while (active) {
            try {
                System.out.println("receiving");
                //String s = in.readLine();
                int length = 4096;
                byte[] buf = new byte[length];
                buf = readBytes();
                System.out.println("fichier recu");
                controller.processSignal(buf);

            } catch (IOException ex) {
                if (active) System.out.println("Error reading from the input file " + ex.getMessage());
            }
        }
        System.out.println("closed NI");
    }

    public void stop() {
        active = false;
        thread.interrupt();
        try {
            socket.close();
            if (server != null) {
                server.close();
            }
        } catch (IOException ex) {
            System.out.println("Error closing TCP sockets");
        }
        System.out.println("closing NI");
    }
}
